package net.quanter.shield.utils.date;

import net.quanter.shield.common.dto.date.DataRegionDTO;
import net.quanter.shield.common.enums.date.Period;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * 时间日期工具类
 * 添加了很多业务项目中需要使用的个性化方法，比如获取周末等
 * 2020-08-08
 *
 * @author 王老实
 * @since 1.3.13.RELEASE
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    /**
     * 用默认时区返回StartTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getStartTimeByPeriod(final Date date, final Period period) {
        return getStartTimeByPeriod(date, period, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用GMT时区返回StartTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getStartTimeByPeriodGMT(final Date date, final Period period) {
        return getStartTimeByPeriod(date, period, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用UTC时区返回StartTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getStartTimeByPeriodUTC(final Date date, final Period period) {
        return getStartTimeByPeriod(date, period, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用中国时区返回StartTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getStartTimeByPeriodChina(final Date date, final Period period) {
        return getStartTimeByPeriod(date, period, TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 返回某个date,返回指定period的起始时间,这个方法很牛逼啊，很有用
     * 尤其在量化里，调用此方法，可以计算出某根K柱的结束时间
     * 2015-01-05 12:13:14 m1 to 2015-01-05 12:13:00
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getStartTimeByPeriod(final Date date, final Period period, TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone == null ? TimeZones.DEFATULT_TIME_ZONE : timeZone);
        calendar.setTime(date == null ? new Date() : date);
        //毫秒怎么都要置0的
        calendar.set(Calendar.MILLISECOND, 0);
        int second = calendar.get(Calendar.SECOND);
        int minute = calendar.get(Calendar.MINUTE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        switch (period) {
            case S1:
                break;
            case S5:
                calendar.set(Calendar.SECOND, second < 5 ? 0 : second - second % 5);
                break;
            case S10:
                calendar.set(Calendar.SECOND, second < 10 ? 0 : second - second % 10);
                break;
            case S15:
                calendar.set(Calendar.SECOND, second < 15 ? 0 : second - second % 15);
                break;
            case S30:
                calendar.set(Calendar.SECOND, second < 30 ? 0 : second - second % 30);
                break;
            case M1:
                calendar.set(Calendar.SECOND, 0);
                break;
            case M2:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 2 ? 0 : minute - minute % 2);
                break;
            case M3:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 3 ? 0 : minute - minute % 3);
                break;
            case M5:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 5 ? 0 : minute - minute % 5);
                break;
            case M10:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 10 ? 0 : minute - minute % 10);
                break;
            case M15:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 15 ? 0 : minute - minute % 15);
                break;
            case M30:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 30 ? 0 : minute - minute % 30);
                break;
            case H1:
                resetHourTime(calendar);
                break;
            case H2:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 2 ? 0 : hour - hour % 2);
                break;
            case H4:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 4 ? 0 : hour - hour % 4);
                break;
            case H6:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 6 ? 0 : hour - hour % 6);
                break;
            case H12:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 12 ? 0 : hour - hour % 12);
                break;
            case WEEK:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_WEEK, 1);
                break;
            case MONTH:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                break;
            case QUARTER:
                resetDayTime(calendar);
                int month = calendar.get(Calendar.MONTH);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                calendar.set(Calendar.MONTH, month < 2 ? 0 : month - month % 3);
                break;
            case YEAR:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_YEAR, 1);
                break;
            case DAY:
            default:
                resetDayTime(calendar);
                break;
        }
        return calendar.getTime();
    }

    /**
     * 用默认时区返回endTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getNextStartTimeByPeriod(final Date date, final Period period) {
        return getNextStartTimeByPeriod(date, period, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用GMT时区返回endTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getNextStartTimeByPeriodGMT(final Date date, final Period period) {
        return getNextStartTimeByPeriod(date, period, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用UTC时区返回endTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getNextStartTimeByPeriodUTC(final Date date, final Period period) {
        return getNextStartTimeByPeriod(date, period, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用中国时区返回endTime
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getNextStartTimeByPeriodChina(final Date date, final Period period) {
        return getNextStartTimeByPeriod(date, period, TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 返回某个date,返回指定period的结束时间,这个方法很牛逼啊，很有用
     * 尤其在量化里，调用此方法，可以计算出某根K柱的结束时间
     * 2015-01-05 12:13:14 m1 to 2015-01-05 12:13:00
     *
     * @param date   2015-01-05 12:13:14.234
     * @param period Period.MONTH
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return 2015-01-01 00:00:00.000
     */
    public static Date getNextStartTimeByPeriod(final Date date, final Period period, final TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone == null ? TimeZones.DEFATULT_TIME_ZONE : timeZone);
        calendar.setTime(date == null ? new Date() : date);
        //毫秒怎么都要置0的
        calendar.set(Calendar.MILLISECOND, 0);
        int second = calendar.get(Calendar.SECOND);
        int minute = calendar.get(Calendar.MINUTE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        switch (period) {
            case S1:
                calendar.add(Calendar.SECOND, 1);
                break;
            case S5:
                calendar.set(Calendar.SECOND, second < 5 ? 0 : second - second % 5);
                calendar.add(Calendar.SECOND, 5);
                break;
            case S10:
                calendar.set(Calendar.SECOND, second < 10 ? 0 : second - second % 10);
                calendar.add(Calendar.SECOND, 10);
                break;
            case S15:
                calendar.set(Calendar.SECOND, second < 15 ? 0 : second - second % 15);
                calendar.add(Calendar.SECOND, 15);
                break;
            case S30:
                calendar.set(Calendar.SECOND, second < 30 ? 0 : second - second % 30);
                calendar.add(Calendar.SECOND, 30);
                break;
            case M1:
                calendar.set(Calendar.SECOND, 0);
                calendar.add(Calendar.MINUTE, 1);
                break;
            case M2:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 2 ? 0 : minute - minute % 2);
                calendar.add(Calendar.MINUTE, 2);
                break;
            case M3:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 3 ? 0 : minute - minute % 3);
                calendar.add(Calendar.MINUTE, 3);
                break;
            case M5:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 5 ? 0 : minute - minute % 5);
                calendar.add(Calendar.MINUTE, 5);
                break;
            case M10:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 10 ? 0 : minute - minute % 10);
                calendar.add(Calendar.MINUTE, 10);
                break;
            case M15:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 15 ? 0 : minute - minute % 15);
                calendar.add(Calendar.MINUTE, 15);
                break;
            case M30:
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MINUTE, minute < 30 ? 0 : minute - minute % 30);
                calendar.add(Calendar.MINUTE, 30);
                break;
            case H1:
                resetHourTime(calendar);
                calendar.add(Calendar.HOUR_OF_DAY, 1);
                break;
            case H2:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 2 ? 0 : hour - hour % 2);
                calendar.add(Calendar.HOUR_OF_DAY, 2);
                break;
            case H4:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 4 ? 0 : hour - hour % 4);
                calendar.add(Calendar.HOUR_OF_DAY, 4);
                break;
            case H6:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 6 ? 0 : hour - hour % 6);
                calendar.add(Calendar.HOUR_OF_DAY, 6);
                break;
            case H12:
                resetHourTime(calendar);
                calendar.set(Calendar.HOUR_OF_DAY, hour < 12 ? 0 : hour - hour % 12);
                calendar.add(Calendar.HOUR_OF_DAY, 12);
                break;
            case WEEK:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_WEEK, 1);
                calendar.add(Calendar.DATE, 7);
                break;
            case MONTH:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                calendar.add(Calendar.MONTH, 1);
                break;
            case QUARTER:
                resetDayTime(calendar);
                int month = calendar.get(Calendar.MONTH);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                calendar.set(Calendar.MONTH, month < 2 ? 0 : month - month % 3);
                calendar.add(Calendar.MONTH, 3);
                break;
            case YEAR:
                resetDayTime(calendar);
                calendar.set(Calendar.DAY_OF_YEAR, 1);
                calendar.add(Calendar.YEAR, 1);
                break;
            case DAY:
            default:
                resetDayTime(calendar);
                calendar.add(Calendar.DATE, 1);
                break;
        }
        return calendar.getTime();
    }

    /**
     * 设置calendar的时间为当然0时0分0秒
     *
     * @param calendar calendar实例
     */
    private static void resetHourTime(Calendar calendar) {
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
    }

    /**
     * 设置calendar的时间为当然0时0分0秒
     *
     * @param calendar calendar实例
     */
    private static void resetDayTime(Calendar calendar) {
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
    }

    /**
     * 获取默认区间时间段
     *
     * @param date   2020-01-01 12:00:00
     * @param period Period.DAY
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDataRegion(final Date date, final Period period, TimeZone timeZone) {
        return new DataRegionDTO(getStartTimeByPeriod(date, period, timeZone), getNextStartTimeByPeriod(date, period, timeZone));
    }

    /**
     * 获取默认区间时间段
     *
     * @param date   2020-01-01 12:00:00
     * @param period Period.DAY
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDataRegion(final Date date, final Period period) {
        return getDataRegion(date, period, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 获取GMT时区的时间段
     *
     * @param date   2020-01-01 12:00:00
     * @param period Period.DAY
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDataRegionGMT(final Date date, final Period period) {
        return getDataRegion(date, period, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 获取UTC时区的时间段
     *
     * @param date   2020-01-01 12:00:00
     * @param period Period.DAY
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDataRegionUTC(final Date date, final Period period) {
        return getDataRegion(date, period, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 获取中国时区的时间段
     *
     * @param date   2020-01-01 12:00:00
     * @param period Period.DAY
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDataRegionChina(final Date date, final Period period) {
        return getDataRegion(date, period, TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 获取从当前时间计算加减n天后（n可以为负数）的起止时间
     *
     * @param days     0
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getDayRegion(final int days, final TimeZone timeZone) {
        Calendar c = Calendar.getInstance();
        c.setTimeZone(timeZone);
        c.add(Calendar.DATE, days);
        return getDataRegion(c.getTime(), Period.DAY, timeZone);
    }

    /**
     * 得到今天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getToday(final TimeZone timeZone) {
        return getDayRegion(0, timeZone);
    }

    /**
     * 得到今天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getToday() {
        return getToday(TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用GMT时区得到今天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getTodayGMT() {
        return getToday(TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用UTC时区得到今天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getTodayUTC() {
        return getToday(TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用中国时区得到今天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-01 00:00:00,2020-01-02 00:00:00]
     */
    public static DataRegionDTO getTodayChina() {
        return getToday(TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 得到昨天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return [2019-12-31 00:00:00,2020-01-01 00:00:00]
     */
    public static DataRegionDTO getYestoday(TimeZone timeZone) {
        return getDayRegion(-1, timeZone);
    }

    /**
     * 用默认时区得到昨天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2019-12-31 00:00:00,2020-01-01 00:00:00]
     */
    public static DataRegionDTO getYestoday() {
        return getYestoday(TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用GMT时区得到昨天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2019-12-31 00:00:00,2020-01-01 00:00:00]
     */
    public static DataRegionDTO getYestodayGMT() {
        return getYestoday(TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用UTC时区得到昨天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2019-12-31 00:00:00,2020-01-01 00:00:00]
     */
    public static DataRegionDTO getYestodayUTC() {
        return getYestoday(TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用中国时区得到昨天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2019-12-31 00:00:00,2020-01-01 00:00:00]
     */
    public static DataRegionDTO getYestodayChina() {
        return getYestoday(TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 得到明天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return [2020-01-02 00:00:00,2020-01-03 00:00:00]
     */
    public static DataRegionDTO getTomorrow(final TimeZone timeZone) {
        return getDayRegion(1, timeZone);
    }

    /**
     * 用默认时区得到明天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-02 00:00:00,2020-01-03 00:00:00]
     */
    public static DataRegionDTO getTomorrow() {
        return getTomorrow(TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用UTC时区得到明天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-02 00:00:00,2020-01-03 00:00:00]
     */
    public static DataRegionDTO getTomorrowUTC() {
        return getTomorrow(TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用GMT时区得到明天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-02 00:00:00,2020-01-03 00:00:00]
     */
    public static DataRegionDTO getTomorrowGMT() {
        return getTomorrow(TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用中国时区得到明天的起止时间
     * e.g currentTime is 2020-01-01 12:00:00
     *
     * @return [2020-01-02 00:00:00,2020-01-03 00:00:00]
     */
    public static DataRegionDTO getTomorrowChina() {
        return getTomorrow(TimeZones.CHINA_TIME_ZONE);
    }/**/

    /**
     * 返回两个时间制定字段的差值
     *
     * @param begin  2015-01-05 12:13:14.234
     * @param end    2015-01-06 12:13:14.234
     * @param period Period.DAY
     * @return 1
     */
    public static int getDiff(Date begin, Date end, Period period) {
        return (int) ((end.getTime() - begin.getTime()) / period.milliSeconds);
    }

    /**
     * 判断是否工作日
     *
     * @param date     2020-02-02
     * @param timeZone CHINA
     * @return false
     */
    public static boolean isWorkDay(Date date, TimeZone timeZone) {
        return !isWeekEnd(date, timeZone);
    }

    /**
     * 判断是否工作日
     *
     * @param date 2020-02-04
     * @return true
     */
    public static boolean isWorkDay(Date date) {
        return !isWeekEnd(date, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 判断是否工作日
     *
     * @param date 2020-02-04
     * @return true
     */
    public static boolean isWorkDayGMT(Date date) {
        return !isWeekEnd(date, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 判断是否工作日
     *
     * @param date 2020-02-04
     * @return true
     */
    public static boolean isWorkDayUTC(Date date) {
        return !isWeekEnd(date, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 判断是否工作日
     *
     * @param date 2020-02-04
     * @return true
     */
    public static boolean isWorkDayChina(Date date) {
        return !isWeekEnd(date, TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 判断是否周末
     *
     * @param date     2020-02-01 12:00:00
     * @param timeZone GMT
     * @return true
     */
    public static boolean isWeekEnd(Date date, TimeZone timeZone) {
        Calendar c = Calendar.getInstance();
        c.setTimeZone(timeZone);
        c.setTime(date);
        int day_of_week = c.get(Calendar.DAY_OF_WEEK);
        return day_of_week == 1 || day_of_week == 7;
    }

    /**
     * 判断是否周末
     *
     * @param date 2020-02-01 12:00:00
     * @return true
     */
    public static boolean isWeekEnd(Date date) {
        return isWeekEnd(date, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 判断是否周末
     *
     * @param date 2020-02-01 12:00:00
     * @return true
     */
    public static boolean isWeekEndGMT(Date date) {
        return isWeekEnd(date, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 判断是否周末
     *
     * @param date 2020-02-01 12:00:00
     * @return true
     */
    public static boolean isWeekEndUTC(Date date) {
        return isWeekEnd(date, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 判断是否周末（周六，周日）
     *
     * @param date 2020-02-01 12:00:00
     * @return true
     */
    public static boolean isWeekEndChina(Date date) {
        return isWeekEnd(date, TimeZones.CHINA_TIME_ZONE);
    }


    /**
     * 得到本月第一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return 2020-01-27 00:00:00
     */
    public static DataRegionDTO getFirstWorkDayForMonth(final Date date, final TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone);
        calendar.setTime(date);
        resetDayTime(calendar);
        //天设为一个月的第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        //计算出这个星期的最后一个工作日，但不能超过本月最后一天
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == Calendar.SATURDAY) {
            calendar.add(Calendar.DATE, 2);
        }
        if (dayOfWeek == Calendar.SUNDAY) {
            calendar.add(Calendar.DATE, 1);
        }
        return getDataRegion(calendar.getTime(), Period.DAY, timeZone);
    }

    /**
     * 用默认时区得到本月第一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @return 2020-01-27 00:00:00
     */
    public static DataRegionDTO getFirstWorkDayForMonth(final Date date) {
        return getFirstWorkDayForMonth(date, TimeZones.DEFATULT_TIME_ZONE);
    }

    /**
     * 用GMT时区得到本月第一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @return 2020-01-27 00:00:00
     */
    public static DataRegionDTO getFirstWorkDayForMonthGMT(final Date date) {
        return getFirstWorkDayForMonth(date, TimeZones.GMT_TIME_ZONE);
    }

    /**
     * 用UTC时区得到本月第一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @return 2020-01-27 00:00:00
     */
    public static DataRegionDTO getFirstWorkDayForMonthUTC(final Date date) {
        return getFirstWorkDayForMonth(date, TimeZones.UTC_TIME_ZONE);
    }

    /**
     * 用中国时区得到本月第一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @return 2020-01-27 00:00:00
     */
    public static DataRegionDTO getFirstWorkDayForMonthChina(final Date date) {
        return getFirstWorkDayForMonth(date, TimeZones.CHINA_TIME_ZONE);
    }

    /**
     * 得到本月最后一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @param timeZone TimeZones.DEFAULT_TIME_ZONE
     * @return 本月最后一个工作日
     */
    public static DataRegionDTO getLastWorkDayForMonth(Date date, TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone);
        calendar.setTime(date);
        //月份+1，得到下个月
        calendar.add(Calendar.MONTH, 1);
        //天设为下一个月的第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        //本月最后一天
        calendar.add(Calendar.DATE, -1);
        //计算出这个星期的最后一个工作日，但不能超过本月最后一天
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == Calendar.SATURDAY) {
            calendar.add(Calendar.DATE, -1);
        }
        if (dayOfWeek == Calendar.SUNDAY) {
            calendar.add(Calendar.DATE, -2);
        }
        return getDataRegion(calendar.getTime(), Period.DAY, timeZone);
    }


    /**
     * 用中国时区得到本月最后一个工作日,计算方法是周日为一个星期的第一天
     *
     * @param date 2020-02-01 12:00:00
     * @return 2019-12-27 00:00:00
     */
    public static DataRegionDTO getLastWorkDayForMonthChina(final Date date) {
        return getLastWorkDayForMonth(date, TimeZones.CHINA_TIME_ZONE);
    }
}
